package org.fujay.commons.langchain4j.rag.prompt.template;

import dev.langchain4j.rag.content.Content;

import java.util.List;

/**
 * 专家角色提示模板
 * 让模型以特定领域专家的角色回答问题
 */
public class ExpertRoleTemplate implements RagPromptTemplate {

    private static final String DEFAULT_TEMPLATE = """
            你是一个%s领域的专家。请基于检索到的信息，以专业的%s领域视角回答问题。
            
            请遵循以下要求：
            1. 使用%s领域的专业术语和框架进行分析
            2. 提供专业、准确、有深度的见解
            3. 基于检索到的信息回答，不要编造内容
            4. 如果无法从检索信息中找到答案，请诚实地表示作为%s专家无法提供准确的回答
            5. 在回答中引用相关的信息来源
            
            检索到的信息：
            %s
            
            用户问题: %s
            
            请在回答末尾附上使用的参考资料来源。""";

    private final String template;
    private final String domain;

    /**
     * 构造函数
     *
     * @param domain 专业领域
     */
    public ExpertRoleTemplate(String domain) {
        this(DEFAULT_TEMPLATE, domain);
    }

    /**
     * 构造函数
     *
     * @param template 模板字符串
     * @param domain   专业领域
     */
    public ExpertRoleTemplate(String template, String domain) {
        this.template = template != null ? template : DEFAULT_TEMPLATE;
        this.domain = domain != null ? domain : "通用";
    }

    @Override
    public String build(String query, List<Content> retrievedContents) {
        StringBuilder formattedContents = new StringBuilder();

        // 格式化检索内容
        for (int i = 0; i < retrievedContents.size(); i++) {
            Content content = retrievedContents.get(i);
            formattedContents.append("参考资料[").append(i + 1).append("]: ");
            formattedContents.append(content.toString()).append("\n");

            // 添加来源信息
            var metadata = content.metadata();
            if (metadata != null) {
                String source = getSourceFromMetadata(metadata);
                if (source != null && !source.isEmpty()) {
                    formattedContents.append("来源: ").append(source).append("\n");
                }
            }

            formattedContents.append("\n");
        }

        // 应用模板
        return String.format(template, domain, domain, domain, domain, formattedContents.toString(), query);
    }

    /**
     * 从元数据中获取来源信息
     *
     * @param metadata 元数据
     * @return 来源信息
     */
    private String getSourceFromMetadata(Object metadata) {
        if (metadata == null) {
            return null;
        }

        // 这里简单处理，实际实现可能需要根据元数据类型进行适配
        if (metadata instanceof java.util.Map) {
            java.util.Map<?, ?> map = (java.util.Map<?, ?>) metadata;

            // 尝试获取常见的来源字段
            for (String field : new String[]{"source", "filename", "url", "title", "path"}) {
                Object value = map.get(field);
                if (value != null) {
                    return value.toString();
                }
            }
        }

        return metadata.toString();
    }
}